package com.zwps.common.minio.service;

import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import lombok.AllArgsConstructor;
import cn.hutool.core.util.StrUtil;
import java.io.InputStream;
import java.net.URLDecoder;
import java.util.LinkedList;
import java.util.List;
import org.springframework.stereotype.Service;

import com.zwps.common.minio.config.MinioConfigProperties;

@Service
@AllArgsConstructor
public class MinioService {

    private MinioConfigProperties minioConfig;

    private MinioClient minioClient;

    public String upload(InputStream stream, String path, String customBucket, String fileName) throws Exception {
        String newBucket = minioConfig.getBucketName();
        if (StrUtil.isNotEmpty(customBucket)) {
            newBucket = customBucket;
        }
        try {
            // 检查存储桶是否已经存在
            if (minioClient.bucketExists(BucketExistsArgs.builder().bucket(newBucket).build())) {
            } else {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(newBucket).build());
            }
            String objectName = path + "/" + fileName;

            // 使用putObject上传一个本地文件到存储桶中。
            if (objectName.startsWith("/")) {
                objectName = objectName.substring(1);
            }
            PutObjectArgs objectArgs = PutObjectArgs.builder().object(objectName).bucket(newBucket)
                    .contentType("application/octet-stream").stream(stream, stream.available(), -1).build();
            minioClient.putObject(objectArgs);
            stream.close();
            return newBucket + "/" + objectName;
        } catch (Exception e) {
            throw new Exception("保存文件失败", e);
        }
    }

    /**
     * 文件上传
     * 
     * @Title: upload
     * @Description:
     * @param stream
     * @param path
     * @param fileName
     * @return 返回文件路径，格式：（<bucketName>/<path>/<fileName>）
     * @throws Exception String
     * @author lyh
     * @date 2023年5月27日 下午2:22:32
     */
    public String upload(InputStream stream, String path, String fileName) throws Exception {
        return upload(stream, path, null, fileName);
    }

    public void move(String srcFilePath, String destFilePath) throws Exception {
        if (srcFilePath.startsWith("/")) {
            srcFilePath = srcFilePath.substring(1);
        }
        if (destFilePath.startsWith("/")) {
            destFilePath = destFilePath.substring(1);
        }
        move(minioConfig.getBucketName(), srcFilePath, minioConfig.getBucketName(), destFilePath);
    }

    /**
     * 获取文件流
     * 
     * @param bucketName
     * @param objectName
     * @return
     */
    public InputStream getMinioFile(String bucketName, String objectName) throws Exception {
        GetObjectArgs objectArgs = GetObjectArgs.builder().object(objectName).bucket(bucketName).build();
        return minioClient.getObject(objectArgs);
    }

    /**
     * 删除文件
     * 
     * @param bucketName
     * @param objectName
     * @throws Exception
     */
    public void removeObject(String bucketName, String objectName) throws Exception {
        RemoveObjectArgs objectArgs = RemoveObjectArgs.builder().object(objectName).bucket(bucketName).build();
        minioClient.removeObject(objectArgs);
    }

    public void removeObjects(String bucketName, List<String> objectNames) throws Exception {
        List<DeleteObject> objects = new LinkedList<>();
        for (String objectName : objectNames) {
            objects.add(new DeleteObject(objectName));
        }
        Iterable<Result<DeleteError>> results = minioClient
                .removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(objects).build());
        for (Result<DeleteError> result : results) {
            DeleteError error = result.get();
            System.out.println("Error in deleting object " + error.objectName() + "; " + error.message());
        }
    }

    /**
     * 获取文件外链
     * 
     * @param bucketName
     * @param objectName
     * @param expires
     * @return
     */
    public String getObjectURL(String bucketName, String objectName, Integer expires) throws Exception {
        GetPresignedObjectUrlArgs objectArgs = GetPresignedObjectUrlArgs.builder().object(objectName).bucket(bucketName)
                .expiry(expires).method(Method.GET).build();
        String url = minioClient.getPresignedObjectUrl(objectArgs);
        return URLDecoder.decode(url, "UTF-8");
    }

    /**
     * 拷贝文件
     *
     * @param srcBucket  原bucket名称
     * @param srcObject  原文件名称
     * @param destBucket 目标bucket名称
     * @param destObject 目标文件名称
     */
    public ObjectWriteResponse copy(String srcBucket, String srcObject, String destBucket, String destObject)
            throws Exception {
        return minioClient.copyObject(
                CopyObjectArgs.builder().source(CopySource.builder().bucket(srcBucket).object(srcObject).build())
                        .bucket(destBucket).object(destObject).build());
    }

    /**
     * 移动文件
     *
     * @param srcBucket  原bucket名称
     * @param srcObject  原文件名称
     * @param destBucket 目标bucket名称
     * @param destObject 目标文件名称
     */
    public void move(String srcBucket, String srcObject, String destBucket, String destObject) throws Exception {
        copy(srcBucket, srcObject, destBucket, destObject);
        removeObject(srcBucket, srcObject);
    }

}
